package echecs.tools;

final class MutableBoard //        extends AbstractBoard
{

    public static final int FILE_COUNT = 8;
    public static final int RANK_COUNT = 8;
    private boolean _whiteActive = true;
    /** Drapeau indiquant le droit de roquer côté roi (petit roque) pour les blancs. */
    private boolean _whiteCastleShort = true;
    /** Drapeau indiquant le droit de roquer côté reine (grand roque) pour les blancs. */
    private boolean _whiteCastleLong = true;
    /** Drapeau indiquant le droit de roquer côté roi (petit roque) pour les noirs. */
    private boolean _blackCastleShort = true;
    /** Drapeau indiquant le droit de roquer côté reine (grand roque) pour les noirs. */
    private boolean _blackCastleLong = true;
    private Square _enPassant;
    /** Numéro du coup. */
    private int _fullmoveNumber = 1;
    private int _halfmoveCount;
    private final Piece[][] _pieces = new Piece[FILE_COUNT][RANK_COUNT];

    MutableBoard() {
    }

    public Piece getPieceAt(final Square pCase) {
        assert pCase != null;

        return getPieceAt(pCase.getFile(), pCase.getRank());
    }

    /**
     * Renvoi l'éventuelle pièce présente sur la case dont les coordonnées sont indiquées.
     *
     * @param pColonne Colonne de la case à tester (de 0 à 7).
     * @param pLigne Ligne de la case à tester (de 0 à 7).
     * @return Pièce présente sur la case (ou null).
     */
    public Piece getPieceAt(final int pColonne, final int pLigne) {
        assert (pColonne >= 0) && (pColonne < FILE_COUNT);
        assert (pLigne >= 0) && (pLigne < RANK_COUNT);

        return _pieces[pColonne][pLigne];
    }

    /**
     * Alimente une case avec une (éventuelle) pièce.
     *
     * @param pPiece Pièce à mettre dans la case (ou null si aucune).
     * @param pCase Cellule cible.
     */
    void setPieceAt(final Piece pPiece, final Square pCase) {
        assert pCase != null;

        _pieces[pCase.getFile()][pCase.getRank()] = pPiece;
    }

    protected void setWhiteActive(final boolean pTrait) {
        _whiteActive = pTrait;
    }

    protected void setCastleLong(final boolean pBlanc, final boolean pEtat) {
        if (pBlanc) {
            _whiteCastleLong = pEtat;
        } else {
            _blackCastleLong = pEtat;
        }
    }

    /**
     * Alimente l'état du droit de roquer côté reine (grand roque) pour une couleur.
     * <p>
     * Potentiellement dangeureux : attention à ne pas casser le contrat qui veut que les
     * implémentations se comportent comme des objets immuables.
     * </p>
     *
     * @param pBlanc Positionné à "true" pour alimenter l'état des blancs.
     * @param pEtat Etat du droit de roquer côté reine pour la couleur.
     */
    protected void setCastleShort(final boolean pBlanc, final boolean pEtat) {
        if (pBlanc) {
            _whiteCastleShort = pEtat;
        } else {
            _blackCastleShort = pEtat;
        }
    }

    protected void setEnPassant(final Square pCase) {
        _enPassant = pCase;
    }

    /**
     * Alimente le numéro du coup.
     * <p>
     * Potentiellement dangeureux : attention à ne pas casser le contrat qui veut que les
     * implémentations se comportent comme des objets immuables.
     * </p>
     *
     * @param pNumero Numéro de coup (> 0).
     */
    protected void setFullmoveNumber(final int pNumero) {
        assert pNumero > 0;
        _fullmoveNumber = pNumero;
    }

    protected void setHalfmoveCount(final int pNombre) {
        assert pNombre >= 0;
        _halfmoveCount = pNombre;
    }
}
